package com.monitor.service.impl;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.core.*;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.indices.CreateIndexResponse;
import co.elastic.clients.json.JsonData;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import com.monitor.model.AccessLog;
import com.monitor.model.ElasticSearchOverView;
import com.monitor.model.ElasticSearchParams;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.monitor.service.ElasticSearchClientService;
import com.monitor.util.ElasticSearchCombineDataUtil;

import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ElasticSearchClientServiceImpl implements ElasticSearchClientService {
    @Autowired
    private ElasticsearchClient elasticsearchClient;

    @Autowired
    private ElasticSearchCombineDataUtil combineDataUtil;

    @Override
    public List<AccessLog> searchInRangeOfRequestTime(ElasticSearchParams params) {
        log.info("searchInRangeOfRequestTime params:{}", JSON.toJSONString(params));
        List<AccessLog> httpLogs = null;
        try {
            SearchResponse<AccessLog> httpLogSearchResponse = elasticsearchClient.search(
                    SearchRequest.of(
                            s -> s.index(params.getIndex())
//                                    .sort(sort -> sort.field(field -> field.field("resp_time").order(SortOrder.Desc)))
                                    .query(q -> q.bool(
                                            builder -> builder.must(
                                                    m -> m.range(
                                                            r -> r.field("req_time.keyword").gte(JsonData.of(params.getStartTime())).lte(JsonData.of(params.getEndTime())))))))
                    , AccessLog.class);
            httpLogs = httpLogSearchResponse.hits().hits().stream().map(Hit::source).collect(Collectors.toList());
            log.info("searchInRangeOfRequestTime results.size:{}", httpLogs.size());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return httpLogs;
    }

    @Override
    public ElasticSearchOverView overview(ElasticSearchParams params) {
        List<AccessLog> httpLogs = searchInRangeOfRequestTime(params);
        return combineDataUtil.combineData(httpLogs);
    }

    @Override
    public boolean createIndex(ElasticSearchParams params) {
        CreateIndexResponse createIndexResponse = null;
        try {
            createIndexResponse = elasticsearchClient.indices().create(c -> c.index(params.getIndex()));
            log.info("createIndexResponse:{}", createIndexResponse.acknowledged());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return createIndexResponse == null ? false : createIndexResponse.acknowledged();
    }

    @Override
    public String createDoc(ElasticSearchParams params) {
        CreateResponse createResponse = null;
        try {
            createResponse = elasticsearchClient.create(CreateRequest.of(c -> c.index(params.getIndex()).type("_doc").document(params.getParam())));
            log.info("createResponse:{}",createResponse.result().jsonValue());
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (createResponse != null) {
            return createResponse.result().jsonValue();
        }
        return "createDocResponse is null";
    }

    @Override
    public String deleteIndex(ElasticSearchParams params) {
        DeleteResponse deleteResponse = null;
        try {
            deleteResponse = elasticsearchClient.delete(DeleteRequest.of(d -> d.index(params.getIndex())));
            log.info("delete response:{}", deleteResponse.result().jsonValue());
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (deleteResponse != null) {
            return deleteResponse.result().jsonValue();
        }
        return "deleteIndexResponse is null";
    }
}
